const db = require('../config/db');
const { successResponse, errorResponse } = require('../utils/responseHandler');

exports.getUserMessages = async (req, res, next) => {
    const userId = req.user.userId; // From authMiddleware
    const userRoles = req.user.roles || []; // Assuming roles are available, e.g., ['role_id_1', 'role_id_2']
    let preferredLanguage = req.query.language;
    if (!preferredLanguage && req.headers['accept-language']) {
        // 解析 Accept-Language 头部，取第一个语言代码
        const acceptLanguage = req.headers['accept-language'];
        const languageMatch = acceptLanguage.match(/([a-z]{2}(-[A-Z]{2})?)/);
        if (languageMatch) {
            preferredLanguage = languageMatch[1].split('-')[0]; // 只取语言代码部分，如 'zh-CN' -> 'zh'
        }
    }
    const language = preferredLanguage || 'zh'; // 默认中文

    // 分页参数
    const offset = parseInt(req.query.offset) || 0;
    const limit = parseInt(req.query.limit) || 10;

    const now = Date.now();

    try {
        // 构建查询参数数组
        const queryParams = [];
        let paramIndex = 0;

        // 基础参数
        queryParams.push(userId); // $1
        queryParams.push(now);    // $2
        queryParams.push(now);    // $3
        paramIndex = 3;

        // 角色条件处理
        let roleCondition = 'FALSE';
        if (userRoles && userRoles.length > 0) {
            const rolePlaceholders = [];
            userRoles.forEach(roleId => {
                paramIndex++;
                rolePlaceholders.push(`$${paramIndex}`);
                queryParams.push(parseInt(roleId));
            });
            roleCondition = `mtr.role_id IN (${rolePlaceholders.join(',')})`;
        }

        // 语言参数
        paramIndex++;
        const languageParam = `$${paramIndex}`;
        queryParams.push(String(language));

        // 分页参数
        paramIndex++;
        const limitParam = `$${paramIndex}`;
        queryParams.push(limit);

        paramIndex++;
        const offsetParam = `$${paramIndex}`;
        queryParams.push(offset);

        // 构建查询
        const messagesQuery = `
            WITH message_with_preferred_content AS (
                SELECT
                    m.id,
                    m.notification_type,
                    m.priority,
                    m.published_at,
                    -- 添加已读状态
                    CASE WHEN mr.id IS NOT NULL THEN true ELSE false END as is_read,
                    -- 优先选择指定语言的内容
                    COALESCE(
                            (SELECT jsonb_build_object(
                                            'title', mc1.title,
                                            'content', mc1.content,
                                            'body', mc1.body,
                                            'language', mc1.language
                                    ) FROM message_content mc1
                             WHERE mc1.message_id = m.id
                               AND mc1.language = ${languageParam}::text
                                AND mc1.title IS NOT NULL
                                AND mc1.title != ''
                 AND mc1.content IS NOT NULL 
                 AND mc1.content != ''
                 LIMIT 1),
                -- 如果指定语言不存在，选择任意一种可用语言
                (SELECT jsonb_build_object(
                    'title', mc2.title,
                    'content', mc2.content,
                    'body', mc2.body,
                    'language', mc2.language
                ) FROM message_content mc2 
                 WHERE mc2.message_id = m.id 
                 AND mc2.title IS NOT NULL 
                 AND mc2.title != ''
                 AND mc2.content IS NOT NULL 
                 AND mc2.content != ''
                 ORDER BY mc2.language 
                 LIMIT 1)
            ) as content_data
                FROM message m
                         LEFT JOIN message_read mr ON m.id = mr.message_id AND mr.user_id = $1
                -- Targeting Logic:
                WHERE
                    m.status = 2 -- Must be published
                  AND m.effective_start_at <= $2
                  AND m.effective_end_at >= $3
                  -- 移除已读过滤条件，改为在排序中处理
                  AND (
                    m.target_type = 1 -- Target all users
                        OR (
                        m.target_type = 2 -- Target specific roles
                            AND EXISTS (
                            SELECT 1 FROM message_target_role mtr
                            WHERE mtr.message_id = m.id AND ${roleCondition}
                        )
                        )
                        OR (
                        m.target_type = 3 -- Target specific users
                            AND EXISTS (
                            SELECT 1 FROM message_target_user mtu
                            WHERE mtu.message_id = m.id AND mtu.user_id = $1
                        )
                        )
                    )
                  -- 确保至少有一种语言的内容存在且不为空
                  AND EXISTS (
                    SELECT 1 FROM message_content mc
                    WHERE mc.message_id = m.id
                      AND mc.title IS NOT NULL
                      AND mc.title != ''
                AND mc.content IS NOT NULL 
                AND mc.content != ''
                )
            )
            SELECT
                id,
                (content_data->>'title') as title,
                (content_data->>'content') as content,
                (content_data->>'body') as body,
                (content_data->>'language') as actual_language,
                notification_type,
                priority,
                published_at,
                is_read
            FROM message_with_preferred_content
            WHERE content_data IS NOT NULL
            -- 调整排序：未读在前，已读在后，然后按优先级和发布时间排序
            ORDER BY
                is_read ASC,           -- 未读(false)在前，已读(true)在后
                priority ASC,          -- 优先级升序
                published_at DESC      -- 发布时间降序
                LIMIT ${limitParam} OFFSET ${offsetParam};
        `;

        const result = await db.query(messagesQuery, queryParams);

        const messages = result.rows.map(row => ({
            id: row.id,
            title: row.title,
            content: row.content,
            read: row.is_read,
            body: row.body || '', // Ensure body is string
            language: row.actual_language, // 返回实际使用的语言
            notification_type: row.notification_type, // Already JSONB, pg driver handles it
            priority: row.priority,
            published_at: Number(row.published_at)
        }));

        successResponse(res, messages,undefined,undefined,{
            offset,
            limit,
            count: messages.length,
            hasMore: messages.length === limit // 如果返回的数量等于limit，可能还有更多数据
        });
    } catch (err) {
        console.error('Query error:', err);
        next(err);
    }
};

exports.markMessageRead = async (req, res, next) => {
    const userId = req.user.userId;
    const { message_id } = req.body;

    if (!message_id) {
        return errorResponse(res, 'message_id is required.', 400);
    }

    try {
        // Check if message exists and is targeted to user (optional, but good for security)
        // For simplicity, we'll just insert. If the message isn't for the user,
        // it won't show up in their list anyway.
        const read_at = Date.now();
        const query = `
            INSERT INTO message_read (message_id, user_id, read_at)
            VALUES ($1, $2, $3)
            ON CONFLICT (message_id, user_id) DO NOTHING; -- Ignore if already read
        `;
        await db.query(query, [message_id, userId, read_at]);
        successResponse(res, null, 'Message marked as read.');
    } catch (err) {
        // Handle potential foreign key constraint violation if message_id is invalid
        if (err.code === '23503') { // foreign_key_violation
             return errorResponse(res, 'Invalid message_id.', 400);
        }
        next(err);
    }
};

exports.markAllMessagesRead = async (req, res, next) => {
    const userId = req.user.userId;
    const userRoles = req.user.roles || [];
    const now = Date.now();
    // No specific language needed for marking read, as it's about message IDs

    const client = await db.getClient();
    try {
        await client.query('BEGIN');

        // 1. Find all unread, currently active messages for the user (similar to getUserMessages logic)
        let queryParams = [userId, now, now];
        let paramIndex = queryParams.length;

        let roleCondition = 'FALSE';
        if (userRoles && userRoles.length > 0) {
            const rolePlaceholders = userRoles.map(() => `$${++paramIndex}`).join(',');
            roleCondition = `mtr.role_id IN (${rolePlaceholders})`;
            queryParams.push(...userRoles.map(r => parseInt(r)));
        }

        const findUnreadQuery = `
            SELECT m.id
            FROM message m
            LEFT JOIN message_read mr ON m.id = mr.message_id AND mr.user_id = $1
            WHERE
                m.status = 2
                AND m.effective_start_at <= $2
                AND m.effective_end_at >= $3
                AND mr.id IS NULL
                AND (
                    m.target_type = 1
                    OR (m.target_type = 2 AND EXISTS (SELECT 1 FROM message_target_role mtr WHERE mtr.message_id = m.id AND ${roleCondition}))
                    OR (m.target_type = 3 AND EXISTS (SELECT 1 FROM message_target_user mtu WHERE mtu.message_id = m.id AND mtu.user_id = $1))
                );
        `;

        const unreadResult = await client.query(findUnreadQuery, queryParams);
        const unreadMessageIds = unreadResult.rows.map(row => row.id);

        if (unreadMessageIds.length > 0) {
            const read_at = Date.now();
            // 2. Insert into message_read for each of them
            // Using a loop for simplicity; for very large numbers, consider batching or unnesting
            for (const messageId of unreadMessageIds) {
                await client.query(
                    `INSERT INTO message_read (message_id, user_id, read_at) VALUES ($1, $2, $3) ON CONFLICT (message_id, user_id) DO NOTHING`,
                    [messageId, userId, read_at]
                );
            }
        }

        await client.query('COMMIT');
        successResponse(res, null, 'All accessible messages marked as read.');
    } catch (err) {
        await client.query('ROLLBACK');
        next(err);
    } finally {
        client.release();
    }
};
